import Obj from "../core/Obj";
import Map, {Entry} from "./Map";
import Set from "../set/Set";
import Collection from "../core/Collection";
import UnsupportedOperationException from "../exceptions/UnsupportedOperationException";

export default class UnmodifiableMap<K, V> extends Obj implements Map<K, V>{
  private readonly map: Map<K, V>;

  public constructor(map: Map<K, V>) {
    super();
    this.map = map;
  }

  [Symbol.iterator]() {
    return this.map[Symbol.iterator]();
  }

  capacity(): number {
    return this.map.capacity();
  }

  clear(): void {
    throw new UnsupportedOperationException(UnmodifiableMap, this.clear);
  }

  containsKey(key: K): boolean {
    return this.map.containsKey(key);
  }

  containsValue(value: V): boolean {
    return this.map.containsValue(value);
  }

  entrySet(): Set<Entry<K, V>> {
    return this.map.entrySet();
  }

  equals(b: Obj): boolean {
    return this.map.equals(b);
  }

  forEach(forEachFunc: (key: K, value: V) => void): void {
    throw new UnsupportedOperationException(UnmodifiableMap, this.forEach);
  }

  get(key: K): V | undefined {
    return this.map.get(key);
  }

  getOrDefault(key: K, defaultValue: V): V {
    return this.map.getOrDefault(key, defaultValue);
  }

  grow(capacity: number): void {
    throw new UnsupportedOperationException(UnmodifiableMap, this.grow);
  }

  hashCode(): number {
    return this.map.hashCode();
  }

  isEmpty(): boolean {
    return this.map.isEmpty();
  }

  isFull(): boolean {
    return this.map.isFull();
  }

  keySet(): Set<K> {
    return this.map.keySet();
  }

  put(key: K, value: V): V | undefined {
    throw new UnsupportedOperationException(UnmodifiableMap, this.put);
  }

  putIfAbsent(key: K, value: V): void {
    throw new UnsupportedOperationException(UnmodifiableMap, this.putIfAbsent);
  }

  remove(key: K): V | undefined {
    throw new UnsupportedOperationException(UnmodifiableMap, this.remove);
  }

  size(): number {
    return this.map.size();
  }

  toString(): string {
    return this.map.toString();
  }

  values(): Collection<V> {
    return this.map.values();
  }
}
